<script lang="ts" setup>
import * as Babylon from "babylonjs";
import "babylonjs-loaders";
import { onMounted, ref } from "vue";

const canvas = document.createElement("canvas");
const babylonjsRef = ref<HTMLDivElement>(null);

// 设置画布宽高
const getCavnasSize = () => {
  const width = babylonjsRef.value?.clientWidth;
  const height = babylonjsRef.value?.clientHeight;
  canvas.width = width;
  canvas.height = height;
};

const init = () => {
  const engine = new Babylon.Engine(canvas, true);
  const scene = new Babylon.Scene(engine);
  const camera = new Babylon.ArcRotateCamera(
    "Camera", // 相机名称
    0, // 水平旋转角度
    0, // 垂直旋转角度
    10, // 相机半径
    Babylon.Vector3.Zero(), // 相机目标点
    scene // 相机所在场景
  );
  camera.attachControl(canvas, true);

  // 创建光源
  const light = new Babylon.HemisphericLight(
    "light", // 光源名称
    new Babylon.Vector3(0, 10, 0), // 光源方向
    scene // 光源所在场景
  );

  const light2 = new Babylon.DirectionalLight(
    "dirLight",
    new Babylon.Vector3(2, -2, -2),
    scene
  );
  light2.intensity = 1;

  const shadowGenerator = new Babylon.ShadowGenerator(1024, light2);
  shadowGenerator.useBlurExponentialShadowMap = true;
  shadowGenerator.useKernelBlur = true;
  shadowGenerator.blurKernel = 64;

  // 加载模型
  Babylon.SceneLoader.Append("/model/", "cat.glb", scene, (gltf) => {
    console.log("gltf", gltf);

    for (const mesh of gltf.meshes) {
      if (mesh.getTotalVertices && mesh.getTotalVertices() > 0) {
        shadowGenerator.getShadowMap().renderList.push(mesh);
      }
    }
  });

  const ground = Babylon.MeshBuilder.CreateGround(
    "ground",
    { width: 200, height: 200 },
    scene
  );
  const groundMaterial: any = new Babylon.StandardMaterial("groundMaterial", scene);
  groundMaterial.diffuseTexture = new Babylon.Texture("/model/pone.jpg", scene);
  groundMaterial.diffuseTexture.uScale = 1;
  groundMaterial.diffuseTexture.vScale = 1;
  groundMaterial.specularColor = new Babylon.Color3(0.6, 0.6, 0.6);
  ground.material = groundMaterial;
  ground.receiveShadows = true;

  const ssr = new Babylon.SSRRenderingPipeline(
    "ssr", // The name of the pipeline
    scene, // The scene to which the pipeline belongs
    [scene.activeCamera], // The list of cameras to attach the pipeline to
    false, // Whether or not to use the geometry buffer renderer (default: false, use the pre-pass renderer)
    Babylon.Constants.TEXTURETYPE_UNSIGNED_BYTE // The texture type used by the SSR effect (default: TEXTURETYPE_UNSIGNED_BYTE)
  );

  ssr.thickness = 0.1;
  ssr.enableSmoothReflections = true;
  ssr.step = 15;

  // 渲染场景
  engine.runRenderLoop(() => {
    scene.render();
  });

  // 监听窗口大小变化
  window.addEventListener("resize", () => {
    engine.resize();
  });
};

onMounted(() => {
  getCavnasSize();
  babylonjsRef.value.appendChild(canvas);
  init();
});
</script>

<template>
  <div id="babylonjs-container" ref="babylonjsRef"></div>
</template>

<style lang="scss" scoped>
#babylonjs-container {
  width: 100%;
  height: calc(100vh - 218px);
}
</style>
